Support documenting a selective package
authorAlex Crichton <alex@alexcrichton.com>
Tue, 25 Nov 2014 05:34:05 +0000 (21:34 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 25 Nov 2014 05:40:35 +0000 (21:40 -0800)
src/bin/doc.rs
src/cargo/ops/cargo_doc.rs
tests/test_cargo_doc.rs

index b94ec30e362740432f5d22e69eb6c45fd06653ab..6e835ed51e0359c9d217ae94435c061b7acdf4cb 100644 (file)
@@ -12,6 +12,7 @@ struct Options {
     flag_no_deps: bool,
     flag_open: bool,
     flag_verbose: bool,
+    flag_package: Option<String>,
 }
 
 pub const USAGE: &'static str = "
@@ -21,17 +22,23 @@ Usage:
     cargo doc [options]
 
 Options:
-    -h, --help              Print this message
-    --open                  Opens the docs in a browser after the operation
-    --no-deps               Don't build documentation for dependencies
-    -j N, --jobs N          The number of jobs to run in parallel
-    --features FEATURES     Space-separated list of features to also build
-    --no-default-features   Do not build the `default` feature
-    --manifest-path PATH    Path to the manifest to document
-    -v, --verbose           Use verbose output
+    -h, --help               Print this message
+    --open                   Opens the docs in a browser after the operation
+    -p SPEC, --package SPEC  Package to document
+    --no-deps                Don't build documentation for dependencies
+    -j N, --jobs N           The number of jobs to run in parallel
+    --features FEATURES      Space-separated list of features to also build
+    --no-default-features    Do not build the `default` feature
+    --manifest-path PATH     Path to the manifest to document
+    -v, --verbose            Use verbose output
 
 By default the documentation for the local package and all dependencies is
 built. The output is all placed in `target/doc` in rustdoc's usual format.
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be documented. If it is not given, then the
+current package is documented. For more information on SPEC and its format, see
+the `cargo help pkgid` command.
 ";
 
 pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
@@ -50,7 +57,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             dev_deps: false,
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
-            spec: None,
+            spec: options.flag_package.as_ref().map(|s| s.as_slice()),
             lib_only: false
         },
     };
index 2a34f7fd4706b26f750b757de502b6c027128ed8..2e7831440716adadf1a5517123133fc2fd75213a 100644 (file)
@@ -1,5 +1,7 @@
+use std::io::fs::PathExtensions;
 use std::collections::HashSet;
 
+use core::PackageIdSpec;
 use core::source::Source;
 use ops;
 use sources::PathSource;
@@ -20,31 +22,41 @@ pub fn doc(manifest_path: &Path,
 
     let mut lib_names = HashSet::new();
     let mut bin_names = HashSet::new();
-    for target in package.get_targets().iter().filter(|t| t.get_profile().is_doc()) {
-        if target.is_lib() {
-            assert!(lib_names.insert(target.get_name()));
-        } else {
-            assert!(bin_names.insert(target.get_name()));
+    if options.compile_opts.spec.is_none() {
+        for target in package.get_targets().iter().filter(|t| t.get_profile().is_doc()) {
+            if target.is_lib() {
+                assert!(lib_names.insert(target.get_name()));
+            } else {
+                assert!(bin_names.insert(target.get_name()));
+            }
         }
-    }
-    for bin in bin_names.iter() {
-        if lib_names.contains(bin) {
-            return Err(human("Cannot document a package where a library and a \
-                              binary have the same name. Consider renaming one \
-                              or marking the target as `doc = false`"))
+        for bin in bin_names.iter() {
+            if lib_names.contains(bin) {
+                return Err(human("Cannot document a package where a library \
+                                  and a binary have the same name. Consider \
+                                  renaming one or marking the target as \
+                                  `doc = false`"))
+            }
         }
     }
 
     try!(ops::compile(manifest_path, &mut options.compile_opts));
 
     if options.open_result {
-        use std::io::fs::PathExtensions;
+        let name = match options.compile_opts.spec {
+            Some(spec) => try!(PackageIdSpec::parse(spec)).get_name().to_string(),
+            None => {
+                match lib_names.iter().nth(0) {
+                    Some(s) => s.to_string(),
+                    None => return Ok(())
+                }
+            }
+        };
 
-        match lib_names.iter().nth(0).map(|l| package.get_absolute_target_dir()
-                                                     .join("doc").join(*l).join("index.html"))
-        {
-            Some(ref path) if path.exists() => open_docs(path),
-            _ => ()
+        let path = package.get_absolute_target_dir().join("doc").join(name)
+                                                    .join("index.html");
+        if path.exists() {
+            open_docs(&path);
         }
     }
 
index 3f74f9282bab8b54c09b77cb21af29fda0328f0d..60525f58699f78ed9c393e070bfda0301eb74ce4 100644 (file)
@@ -206,3 +206,41 @@ Cannot document a package where a library and a binary have the same name. \
 Consider renaming one or marking the target as `doc = false`
 "));
 })
+
+test!(doc_dash_p {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies.a]
+            path = "a"
+        "#)
+        .file("src/lib.rs", "extern crate a;")
+        .file("a/Cargo.toml", r#"
+            [package]
+            name = "a"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies.b]
+            path = "../b"
+        "#)
+        .file("a/src/lib.rs", "extern crate b;")
+        .file("b/Cargo.toml", r#"
+            [package]
+            name = "b"
+            version = "0.0.1"
+            authors = []
+        "#)
+        .file("b/src/lib.rs", "");
+
+    assert_that(p.cargo_process("doc").arg("-p").arg("a"),
+                execs().with_status(0)
+                       .with_stdout(format!("\
+{compiling} b v0.0.1 (file://[..])
+{compiling} a v0.0.1 (file://[..])
+", compiling = COMPILING).as_slice()));
+})